import jsPDF from 'jspdf';
import html2canvas from 'html2canvas';
import { saveAs } from 'file-saver';
import { PDFExportOptions, ExportResult, ExportProgress, DEFAULT_PDF_OPTIONS } from './types';

export class PDFExportService {
  private progressCallback?: (progress: ExportProgress) => void;

  constructor(progressCallback?: (progress: ExportProgress) => void) {
    this.progressCallback = progressCallback;
  }

  /**
   * 导出内容为PDF文件
   */
  async exportToPDF(
    content: string, 
    options: Partial<PDFExportOptions> = {}, 
    filename?: string
  ): Promise<ExportResult> {
    try {
      const fullOptions = { ...DEFAULT_PDF_OPTIONS, ...options };
      const finalFilename = filename || this.generateFilename();

      this.reportProgress('preparing', 0, '准备导出内容...');

      // 创建临时HTML元素
      const htmlElement = this.formatContentForPDF(content, fullOptions);
      document.body.appendChild(htmlElement);

      this.reportProgress('converting', 25, '转换内容为图像...');

      // 使用html2canvas转换为画布
      const canvas = await html2canvas(htmlElement, {
        scale: this.getCanvasScale(fullOptions.quality),
        useCORS: true,
        allowTaint: true,
        backgroundColor: '#ffffff',
        logging: false
      });

      // 清理临时元素
      document.body.removeChild(htmlElement);

      this.reportProgress('generating', 50, '生成PDF文档...');

      // 创建PDF文档
      const pdf = this.createPDFDocument(fullOptions);
      
      // 计算页面尺寸
      const pageWidth = pdf.internal.pageSize.getWidth();
      const pageHeight = pdf.internal.pageSize.getHeight();
      const margins = fullOptions.margins;
      const contentWidth = pageWidth - margins.left - margins.right;
      const contentHeight = pageHeight - margins.top - margins.bottom;

      // 添加图像到PDF
      const imgData = canvas.toDataURL('image/jpeg', 0.85);
      const imgWidth = contentWidth;
      const imgHeight = (canvas.height * contentWidth) / canvas.width;

      // 处理多页内容
      let heightLeft = imgHeight;
      let position = margins.top;

      // 添加水印
      if (fullOptions.watermark) {
        this.addWatermark(pdf, fullOptions.watermark, pageWidth, pageHeight);
      }

      // 添加第一页
      pdf.addImage(imgData, 'JPEG', margins.left, position, imgWidth, imgHeight);
      heightLeft -= contentHeight;

      // 添加额外页面
      while (heightLeft >= 0) {
        position = heightLeft - imgHeight + margins.top;
        pdf.addPage();
        
        if (fullOptions.watermark) {
          this.addWatermark(pdf, fullOptions.watermark, pageWidth, pageHeight);
        }
        
        pdf.addImage(imgData, 'JPEG', margins.left, position, imgWidth, imgHeight);
        heightLeft -= contentHeight;
      }

      // 添加元数据
      if (fullOptions.includeMetadata) {
        this.addMetadata(pdf, finalFilename);
      }

      this.reportProgress('saving', 75, '保存PDF文件...');

      // 保存文件
      const blob = pdf.output('blob');
      saveAs(blob, `${finalFilename}.pdf`);

      this.reportProgress('completed', 100, '导出完成');

      return {
        success: true,
        filename: `${finalFilename}.pdf`,
        size: blob.size
      };

    } catch (error) {
      console.error('[PDFExportService] 导出失败:', error);
      return {
        success: false,
        error: error instanceof Error ? error.message : '导出失败'
      };
    }
  }

  /**
   * 格式化内容为PDF友好的HTML
   */
  private formatContentForPDF(content: string, options: PDFExportOptions): HTMLElement {
    const container = document.createElement('div');
    container.style.position = 'absolute';
    container.style.left = '-9999px';
    container.style.top = '0';
    container.style.width = '794px'; // A4宽度像素
    container.style.backgroundColor = '#ffffff';
    container.style.fontFamily = options.fontFamily;
    container.style.fontSize = `${options.fontSize}px`;
    container.style.lineHeight = '1.6';
    container.style.color = '#333333';
    container.style.padding = '40px';
    container.style.boxSizing = 'border-box';

    // 处理Markdown内容
    const htmlContent = this.markdownToHTML(content);
    container.innerHTML = htmlContent;

    // 应用PDF样式
    this.applyPDFStyles(container);

    return container;
  }

  /**
   * 将Markdown转换为HTML
   */
  private markdownToHTML(markdown: string): string {
    return markdown
      // 标题
      .replace(/^### (.*$)/gim, '<h3>$1</h3>')
      .replace(/^## (.*$)/gim, '<h2>$1</h2>')
      .replace(/^# (.*$)/gim, '<h1>$1</h1>')
      // 粗体
      .replace(/\*\*(.*)\*\*/gim, '<strong>$1</strong>')
      // 斜体
      .replace(/\*(.*)\*/gim, '<em>$1</em>')
      // 代码块
      .replace(/```([^`]*)```/gim, '<pre><code>$1</code></pre>')
      // 行内代码
      .replace(/`([^`]*)`/gim, '<code>$1</code>')
      // 链接
      .replace(/\[([^\]]*)\]\(([^)]*)\)/gim, '<a href="$2">$1</a>')
      // 列表
      .replace(/^\* (.*$)/gim, '<li>$1</li>')
      .replace(/(<li>.*<\/li>)/gims, '<ul>$1</ul>')
      // 段落
      .replace(/\n\n/gim, '</p><p>')
      .replace(/^(.*)$/gim, '<p>$1</p>')
      // 清理空段落
      .replace(/<p><\/p>/gim, '');
  }

  /**
   * 应用PDF特定样式
   */
  private applyPDFStyles(element: HTMLElement): void {
    const styles = `
      h1, h2, h3 {
        color: #2c3e50;
        margin: 20px 0 10px 0;
        page-break-after: avoid;
      }
      h1 { font-size: 24px; font-weight: bold; }
      h2 { font-size: 20px; font-weight: bold; }
      h3 { font-size: 16px; font-weight: bold; }
      p {
        margin: 8px 0;
        text-align: justify;
        line-height: 1.6;
      }
      strong {
        font-weight: bold;
        color: #2c3e50;
      }
      em {
        font-style: italic;
        color: #666;
      }
      code {
        background-color: #f8f9fa;
        border: 1px solid #e9ecef;
        border-radius: 3px;
        padding: 2px 4px;
        font-family: 'Consolas', 'Monaco', monospace;
        font-size: 11px;
      }
      pre {
        background-color: #f8f9fa;
        border: 1px solid #e9ecef;
        border-radius: 4px;
        padding: 12px;
        margin: 12px 0;
        overflow-x: auto;
        page-break-inside: avoid;
      }
      ul {
        margin: 10px 0;
        padding-left: 20px;
      }
      li {
        margin: 4px 0;
        list-style-type: disc;
      }
      a {
        color: #007bff;
        text-decoration: underline;
      }
    `;

    const styleElement = document.createElement('style');
    styleElement.textContent = styles;
    element.appendChild(styleElement);
  }

  /**
   * 创建PDF文档
   */
  private createPDFDocument(options: PDFExportOptions): jsPDF {
    const format = options.format.toLowerCase() as 'a4' | 'a3' | 'letter';
    
    return new jsPDF({
      orientation: options.orientation,
      unit: 'mm',
      format: format
    });
  }

  /**
   * 添加水印
   */
  private addWatermark(pdf: jsPDF, watermark: string, pageWidth: number, pageHeight: number): void {
    pdf.setTextColor(200, 200, 200);
    pdf.setFontSize(40);
    pdf.text(watermark, pageWidth / 2, pageHeight / 2, {
      angle: 45,
      align: 'center'
    });
  }

  /**
   * 添加PDF元数据
   */
  private addMetadata(pdf: jsPDF, title: string): void {
    pdf.setProperties({
      title: title,
      creator: '融媒智创工坊',
      author: '融媒智创工坊用户',
      subject: '文档导出',
      keywords: 'document, export, pdf'
    });
  }

  /**
   * 获取画布缩放比例
   */
  private getCanvasScale(quality: 'low' | 'medium' | 'high'): number {
    switch (quality) {
      case 'low': return 1;
      case 'medium': return 2;
      case 'high': return 3;
      default: return 2;
    }
  }

  /**
   * 生成文件名
   */
  private generateFilename(): string {
    const now = new Date();
    const timestamp = now.getFullYear() + 
      String(now.getMonth() + 1).padStart(2, '0') + 
      String(now.getDate()).padStart(2, '0') + '_' +
      String(now.getHours()).padStart(2, '0') + 
      String(now.getMinutes()).padStart(2, '0');
    return `文档_${timestamp}`;
  }

  /**
   * 报告导出进度
   */
  private reportProgress(stage: ExportProgress['stage'], progress: number, message: string): void {
    if (this.progressCallback) {
      this.progressCallback({ stage, progress, message });
    }
  }
}